#include "clientprediction.h"
#include <QDebug>
#include <QApplication>
#include <QtMath>

ClientPrediction::ClientPrediction(QObject *parent)
    : QObject(parent)
    , m_predictionTimer(new QTimer(this))
    , m_nextSequenceNumber(1)
    , m_networkLatency(50)
    , m_lastServerTimestamp(0)
    , m_predictionEnabled(true)
    , m_reconciliationThreshold(0.1f)
    , m_maxInputHistory(50)
    , m_predictionCount(0)
    , m_correctionCount(0)
    , m_mapWidth(40)
    , m_mapHeight(30)
    , m_enableWalls(true)
    , m_averageError(0.0f)
{
    // 初始化预测状态
    m_currentState.isValid = false;
    m_lastServerState.isValid = false;
    
    // 设置60FPS预测定时器
    m_predictionTimer->setInterval(16); // 16ms = 60FPS
    connect(m_predictionTimer, &QTimer::timeout, this, &ClientPrediction::onPredictionTick);
    
    qDebug() << "ClientPrediction: 客户端预测系统初始化完成";
    qDebug() << "  预测频率: 60FPS";
    qDebug() << "  网络延迟补偿:" << m_networkLatency << "ms";
    qDebug() << "  最大输入历史:" << m_maxInputHistory;
}

void ClientPrediction::handleUserInput(int direction)
{
    qDebug() << "ClientPrediction: 处理用户输入:" << direction;
    
    // 创建输入命令
    InputCommand command;
    command.direction = direction;
    command.timestamp = QDateTime::currentMSecsSinceEpoch();
    command.sequenceNumber = m_nextSequenceNumber++;
    command.acknowledged = false;
    
    // 添加到输入历史
    m_inputHistory.enqueue(command);
    
    // 限制历史大小
    while (m_inputHistory.size() > m_maxInputHistory) {
        m_inputHistory.dequeue();
    }
    
    // 立即进行预测
    if (m_currentState.isValid) {
        PredictedState newState = predictNextState(m_currentState, direction);
        m_currentState = newState;
        m_currentState.direction = direction; // 更新方向
        
        qDebug() << "  预测新状态 - 蛇长度:" << newState.snakeBody.size() 
                 << "方向:" << direction;
        
        emit predictedStateUpdated(m_currentState);
    }
    
    // 发送到服务器
    emit sendInputToServer(direction, command.sequenceNumber);
    
    m_predictionCount++;
}

void ClientPrediction::receiveServerState(const QList<QPoint> &snakeBody, int direction, 
                                        qint64 serverTimestamp, int score)
{
    qDebug() << "ClientPrediction: 接收服务器状态";
    qDebug() << "  蛇长度:" << snakeBody.size() << "方向:" << direction 
             << "分数:" << score;
    
    // 创建服务器状态
    PredictedState serverState;
    serverState.snakeBody = snakeBody;
    serverState.direction = direction;
    serverState.timestamp = serverTimestamp;
    serverState.score = score;
    serverState.isValid = true;
    
    // 如果这是第一次接收状态，直接使用
    if (!m_currentState.isValid) {
        m_currentState = serverState;
        m_lastServerState = serverState;
        qDebug() << "  首次接收状态，直接应用";
        qDebug() << "    蛇头位置:" << (serverState.snakeBody.isEmpty() ? QPoint(-1, -1) : serverState.snakeBody.first());
        qDebug() << "    蛇身长度:" << serverState.snakeBody.size();
        emit predictedStateUpdated(m_currentState);
        return;
    }
    
    // 计算预测误差
    float error = calculateStateDifference(m_currentState, serverState);
    m_averageError = (m_averageError * m_correctionCount + error) / (m_correctionCount + 1);
    
    qDebug() << "  预测误差:" << error << "平均误差:" << m_averageError;
    
    // 如果误差超过阈值，进行校正
    if (error > m_reconciliationThreshold) {
        qDebug() << "  误差超过阈值，进行校正";
        reconcileWithServer(serverState);
        m_correctionCount++;
        emit predictionError(error);
    }
    
    m_lastServerState = serverState;
    m_lastServerTimestamp = serverTimestamp;
}

void ClientPrediction::setNetworkLatency(int latencyMs)
{
    m_networkLatency = latencyMs;
    qDebug() << "ClientPrediction: 网络延迟更新为:" << latencyMs << "ms";
}

void ClientPrediction::setCurrentFoods(const QList<QPoint> &foods)
{
    m_currentFoods = foods;
    qDebug() << "ClientPrediction: 更新食物位置，数量:" << foods.size();
}

void ClientPrediction::startPrediction()
{
    if (!m_predictionTimer->isActive()) {
        m_predictionTimer->start();
        qDebug() << "ClientPrediction: 预测系统已启动";
    }
}

void ClientPrediction::stopPrediction()
{
    if (m_predictionTimer->isActive()) {
        m_predictionTimer->stop();
        qDebug() << "ClientPrediction: 预测系统已停止";
    }
}

void ClientPrediction::setMapConfig(int width, int height, bool enableWalls)
{
    qDebug() << "ClientPrediction: 设置地图配置";
    qDebug() << "  地图尺寸:" << width << "x" << height;
    qDebug() << "  墙壁碰撞:" << (enableWalls ? "启用" : "禁用");

    m_mapWidth = width;
    m_mapHeight = height;
    m_enableWalls = enableWalls;
}

ClientPrediction::PredictedState ClientPrediction::getCurrentState() const
{
    return m_currentState;
}

void ClientPrediction::onPredictionTick()
{
    if (!m_predictionEnabled || !m_currentState.isValid) {
        return;
    }
    
    // 基于当前方向进行预测更新
    // 这里主要是为了保持60FPS的状态更新
    emit predictedStateUpdated(m_currentState);
}

ClientPrediction::PredictedState ClientPrediction::predictNextState(const PredictedState &currentState, int direction)
{
    PredictedState newState = currentState;

    if (currentState.snakeBody.isEmpty()) {
        return newState;
    }

    // 计算新的蛇头位置
    QPoint currentHead = currentState.snakeBody.first();
    QPoint newHead = currentHead;

    switch (direction) {
        case 0: // UP
            newHead.setY(currentHead.y() - 1);
            break;
        case 1: // DOWN
            newHead.setY(currentHead.y() + 1);
            break;
        case 2: // LEFT
            newHead.setX(currentHead.x() - 1);
            break;
        case 3: // RIGHT
            newHead.setX(currentHead.x() + 1);
            break;
    }

    // 边界检测（使用动态地图配置）
    if (m_enableWalls) {
        // 墙壁碰撞检测
        if (newHead.x() < 0 || newHead.x() >= m_mapWidth || newHead.y() < 0 || newHead.y() >= m_mapHeight) {
            qDebug() << "ClientPrediction: 预测到墙壁碰撞！位置:" << newHead
                     << "地图尺寸:" << m_mapWidth << "x" << m_mapHeight;
            // 标记为死亡状态，但不修改位置
            newState.isValid = false;
            return newState;
        }
    } else {
        // 环绕模式（穿墙）
        if (newHead.x() < 0) newHead.setX(m_mapWidth - 1);
        if (newHead.x() >= m_mapWidth) newHead.setX(0);
        if (newHead.y() < 0) newHead.setY(m_mapHeight - 1);
        if (newHead.y() >= m_mapHeight) newHead.setY(0);
    }

    // 更新蛇身体
    newState.snakeBody.prepend(newHead);

    // 检查是否吃到食物（使用实时食物位置）
    bool ateFood = false;
    QPoint eatenFood;

    for (const QPoint &food : m_currentFoods) {
        if (newHead == food) {
            ateFood = true;
            eatenFood = food;
            newState.score += 10;
            qDebug() << "ClientPrediction: 吃到食物！位置:" << food << "分数:" << newState.score;

            // 发送食物被吃事件
            emit foodEaten(eatenFood);
            break;
        }
    }

    // 如果没有吃到食物，移除尾部
    if (!ateFood && newState.snakeBody.size() > 1) {
        newState.snakeBody.removeLast();
    }

    // 检查自撞
    for (int i = 1; i < newState.snakeBody.size(); ++i) {
        if (newHead == newState.snakeBody[i]) {
            qDebug() << "ClientPrediction: 蛇撞到自己！";
            // 这里可以触发游戏结束事件
            break;
        }
    }

    newState.direction = direction;
    newState.timestamp = QDateTime::currentMSecsSinceEpoch();

    return newState;
}

void ClientPrediction::reconcileWithServer(const PredictedState &serverState)
{
    qDebug() << "ClientPrediction: 开始服务器校正";
    
    // 使用服务器状态作为基础
    m_currentState = serverState;
    
    // 重新应用未确认的输入
    reapplyUnacknowledgedInputs();
    
    qDebug() << "  校正完成，当前状态 - 蛇长度:" << m_currentState.snakeBody.size();
}

void ClientPrediction::reapplyUnacknowledgedInputs()
{
    qDebug() << "ClientPrediction: 重新应用未确认输入，数量:" << m_inputHistory.size();
    
    // 从服务器状态开始，重新应用所有未确认的输入
    PredictedState state = m_lastServerState;
    
    for (const InputCommand &command : m_inputHistory) {
        if (!command.acknowledged && command.timestamp > m_lastServerTimestamp) {
            state = predictNextState(state, command.direction);
        }
    }
    
    m_currentState = state;
}

float ClientPrediction::calculateStateDifference(const PredictedState &state1, const PredictedState &state2)
{
    if (!state1.isValid || !state2.isValid) {
        return 1.0f; // 完全不同
    }
    
    // 简单的差异计算：比较蛇头位置
    if (state1.snakeBody.isEmpty() || state2.snakeBody.isEmpty()) {
        return 1.0f;
    }
    
    QPoint head1 = state1.snakeBody.first();
    QPoint head2 = state2.snakeBody.first();
    
    float distance = qSqrt(qPow(head1.x() - head2.x(), 2) + qPow(head1.y() - head2.y(), 2));
    
    // 归一化到0-1范围
    return qMin(distance / 10.0f, 1.0f);
}
